﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;

namespace erse253_homework
{
    public partial class ColorMap : BaseWindow
    {
        double min;
        double max;
        double[,] data;
        double[,] original;

        public ColorMap(double[,] data)
        {
            InitializeComponent();

            if (data != null)
            {
               
                this.data = data;


                NumericalSolutions solutions = new NumericalSolutions();

                min = solutions.Min(data);
                max = solutions.Max(data);
                this.textBox1.Text = min.ToString();
                this.textBox2.Text = max.ToString();
                this.textBox3.Text = ((max - min) / 100).ToString();
                GenerateMap(data);
            }
        }

        public ColorMap(double[,] estimated, double[,] original)
        {
            InitializeComponent();


                this.data = estimated;
                this.original = original;

                NumericalSolutions solutions = new NumericalSolutions();

                min = solutions.Min(data);
                max = solutions.Max(data);
                this.textBox1.Text = min.ToString();
                this.textBox2.Text = max.ToString();
                this.textBox3.Text = ((max - min) / 100).ToString();
                GenerateMap(data);
            
        }

        private double[,] RotateData(double[,] data) 
        {
            double[,] rotatedData = new double[data.GetLength(0), data.GetLength(1)];

            for(int i = 0; i < data.GetLength(0); i++)
                for (int j = 0; j < data.GetLength(1); j++) 
                {
                    rotatedData[i, data.GetLength(1) - j-1] = data[i, j];
                }

            return rotatedData;

        }

        private void GenerateMap(double[,] data) 
        {
            double imagerange = Convert.ToDouble(max - min);

            if (data != null)
            {
                Bitmap bmp = new Bitmap(data.GetLength(0), data.GetLength(1));
                bmp = new Bitmap(data.GetLength(0), data.GetLength(1), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, data.GetLength(0), data.GetLength(1)), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);

                GenerateImage(data, imagerange, bmd);

                bmp.UnlockBits(bmd);
                pictureBox1.Image = bmp;
                UpdateColorBar();
                pictureBox1.Update();
            }
        }

        private void GenerateFrame(double[,] data)
        {
            if (data != null)
            {
                double imagerange = Convert.ToDouble(max - min);

                Bitmap bmp = new Bitmap(data.GetLength(0), data.GetLength(1));
                bmp = new Bitmap(data.GetLength(0), data.GetLength(1), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, data.GetLength(0), data.GetLength(1)), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);

                GenerateFrame(data, bmd);
                bmp.UnlockBits(bmd);
                pictureBox1.Image = bmp;

                pictureBox1.Update();
            }
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            if (this.textBox1.Text != string.Empty)
            {
                this.min = Convert.ToDouble(this.textBox1.Text.ToString());
                GenerateMap(data);
            }
        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {
            if (this.textBox2.Text != string.Empty)
            {
                this.max = Convert.ToDouble(this.textBox2.Text.ToString());
                GenerateMap(data);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {

            if (this.textBox3.Text != string.Empty)
            {
                int NumberofFrames = (int)((max - min) / Convert.ToDouble(this.textBox3.Text.ToString()));

                for (int i = 0; i < NumberofFrames + 1; i++)
                {
                    GenerateFrame(data);
                    UpdateColorBarFrame();
                    min += Convert.ToDouble(this.textBox3.Text.ToString());
                    System.Threading.Thread.Sleep(200);
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            NumericalSolutions solutions = new NumericalSolutions();
            min = solutions.Min(data);
            max = solutions.Max(data);
            this.textBox1.Text = min.ToString();
            this.textBox2.Text = max.ToString();
            GenerateMap(data);
        }

        private void UpdateColorBar() 
        {

            Bitmap bmp = new Bitmap(pictureBox2.Width, pictureBox2.Height);
            double imagerange = (max - min) / pictureBox2.Height;
            bmp = new Bitmap(pictureBox2.Width, pictureBox2.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, pictureBox2.Width, pictureBox2.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);

            GenerateColorBar(imagerange, bmd);
            bmp.UnlockBits(bmd);
            pictureBox2.Image = bmp;
            pictureBox2.Update();


            label8.Text = Math.Round(min, 2).ToString();
            label7.Text = Math.Round((min + (max-min)/4 ), 2).ToString();
            label6.Text = Math.Round((min + (max - min) / 2), 2).ToString();
            label5.Text = Math.Round((min + 3*(max - min) / 4), 2).ToString();
            label4.Text = Math.Round(max, 2).ToString();

            label8.Update();
            label7.Update();
            label6.Update();
            label5.Update();
            label4.Update();
   
        }

        private void UpdateColorBarFrame()
        {

            Bitmap bmp = new Bitmap(pictureBox2.Width, pictureBox2.Height);
            double imagerange = (max - min) / pictureBox2.Height;
            bmp = new Bitmap(pictureBox2.Width, pictureBox2.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, pictureBox2.Width, pictureBox2.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);

            GenerateColorBarFrame(imagerange, bmd);
            bmp.UnlockBits(bmd);
            pictureBox2.Image = bmp;
            pictureBox2.Update();


            label8.Text = Math.Round(Convert.ToDouble(textBox1.Text), 2).ToString();
            label7.Text = string.Empty;
            label6.Text = Math.Round(min, 2).ToString();
            label5.Text = string.Empty;
            label4.Text = Math.Round(max, 2).ToString();

            label8.Update();
            label7.Update();
            label6.Update();
            label5.Update();
            label4.Update();
        }

        unsafe private void GenerateImage(double[,] data, double imagerange, BitmapData bmd)
        {
            unsafe
            {
                double b;

                for (int i = 0; i < bmd.Height; ++i)
                {
                    byte* row = (byte*)bmd.Scan0 + (i * bmd.Stride);
                    for (int j = 0; j < bmd.Width; ++j)
                    {

                        if (double.IsNaN(data[j, i]))
                        {
                            row[j * 3] = 255;           // Red
                            row[j * 3 + 1] = 255;            // Green
                            row[j * 3 + 2] = 255;   // Blue
                        }

                        else
                        {
                            b = Convert.ToDouble(data[j, i] - min) * 255.0 / imagerange;


                            if (b > 255)
                                b = 255;

                            if (b < 0)
                                b = 0;


                            
                            row[j * 3 + 1] = (byte)b;            // Green
                            row[j * 3] = (byte)b;           // Red
                            row[j * 3 + 2] = (byte)b; 
                                
                            
                        }      
                    }
                }
            } // end unsafe   
        }

        unsafe private void GenerateFrame(double[,] data, BitmapData bmd)
        {
            unsafe
            {

                byte b;

                for (int i = 0; i < bmd.Height; ++i)
                {
                    byte* row = (byte*)bmd.Scan0 + (i * bmd.Stride);
                    for (int j = 0; j < bmd.Width; ++j)
                    {
                        if (data[j, i] > min)
                            b = 255;
                        else
                            b = 0;


                        row[j * 3] = b;            // Red
                        row[j * 3 + 1] = b;            // Green
                        row[j * 3 + 2] = b;            // Blue


                    }
                }
            } // end unsafe   
        }

        unsafe private void GenerateColorBar(double imagerange, BitmapData bmd)
        {
            unsafe
            {

                double b;

                for (int i = 0; i < bmd.Height; ++i)
                {
                    byte* row = (byte*)bmd.Scan0 + (i * bmd.Stride);
                    for (int j = 0; j < bmd.Width; ++j)
                    {
                        b = 255 * (max - i * imagerange - min) / (max - min);


                        if (b > 255)
                            b = 255;

                        if (b < 0)
                            b = 0;

                         
                        row[j * 3 + 1] = (byte)b;            // Green
                        row[j * 3] = (byte)b;           // Red
                        row[j * 3 + 2] = (byte)b; 
                            

                    }
                }
            } // end unsafe   
        }

        unsafe private void GenerateColorBarFrame(double imagerange, BitmapData bmd)
        {
            unsafe
            {

                double b;

                for (int i = 0; i < bmd.Height; ++i)
                {
                    byte* row = (byte*)bmd.Scan0 + (i * bmd.Stride);
                    for (int j = 0; j < bmd.Width; ++j)
                    {
                        if (i < bmd.Height / 2)
                            b = 255;
                        else
                            b = 0;

                        row[j * 3] = (byte)b;            // Red
                        row[j * 3 + 1] = (byte)b;            // Green
                        row[j * 3 + 2] = (byte)b;            // Blue


                    }
                }
            } // end unsafe   
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {
            Clipboard.SetImage(pictureBox1.Image);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            Auxiliar_Forms.StaticalTool statistical = new Auxiliar_Forms.StaticalTool(data);
            statistical.Show();
        }

        private void button4_Click(object sender, EventArgs e)
        {
            qqSimilarity similarity = new qqSimilarity(original, data);
            similarity.Show();
        }

        private void button5_Click(object sender, EventArgs e)
        {
            Auxiliar_Forms.StaticalTool statistical = new Auxiliar_Forms.StaticalTool(original);
            statistical.Show();
        }

        private void button6_Click(object sender, EventArgs e)
        {
            double[,] difference = new double[data.GetLength(0), data.GetLength(1)];
            for (int i = 0; i < data.GetLength(0); i++)
                for (int j = 0; j < data.GetLength(1); j++)
                {
                    if (!double.IsNaN(data[i, j]) && !double.IsNaN(original[i, j]))
                        difference[i, j] = original[i, j] - data[i, j];
                    else
                        difference[i, j] = double.NaN;
                    }

            Auxiliar_Forms.StaticalTool statistical = new Auxiliar_Forms.StaticalTool(difference);
            statistical.Show();
        }
    }
}
